﻿Imports System.Xml.Serialization

Namespace Commands

    Public Class GetShareItems
        Friend Shared ReadOnly RequestCode As String = "GetShareItems"
        Friend Shared ReadOnly ReplyCode As String = "GetShareItemsReply"

        Private Sub New()
        End Sub

        Public Class Request
            <XmlAttribute()> Public ShareId As Integer
            <XmlText()> Public DirectoryCode As String
        End Class
        Public Class Reply
            <XmlAttribute()> Public InReplyToMessageId As Integer
            Public Groups As New Generic.List(Of Group)
        End Class
        Public Class Group
            <XmlAttribute()> Public Name As String
            <XmlAttribute()> Public Hidden As Boolean
            Public Directories As New Generic.List(Of Directory)
            Public Items As New Generic.List(Of Entities.SharedItem)
            Public Sub New()
            End Sub
            Public Sub New(ByVal name As String)
                Me.Name = name
            End Sub
            Public Sub New(ByVal name As String, ByVal hidden As Boolean)
                Me.Name = name : Me.Hidden = hidden
            End Sub
        End Class
        Public Class Directory
            <XmlAttribute()> Public Code As String
            <XmlAttribute()> Public IsSeparator As Boolean
            <XmlText()> Public Name As String
            Public Sub New()
            End Sub
            Public Sub New(ByVal code As String, ByVal name As String)
                Me.Code = code : Me.Name = name
            End Sub
            Public Sub New(ByVal isSeparator As Boolean)
                Me.IsSeparator = isSeparator
            End Sub
        End Class

        Friend Shared Function SendRequest(ByVal client As NetNode.Client, ByVal share As Entities.SharedWatchFolder, ByVal directoryCode As String) As Integer
            Dim clsRequest As New Request
            clsRequest.ShareId = share.Id
            clsRequest.DirectoryCode = directoryCode
            Dim strMessage As String = RequestCode
            Dim aData() As Byte = Utils.Serialization.ToXmlBytes(clsRequest)
            Return client.SendMessageToTargetAsync(Manager.TargetName, strMessage, aData)
        End Function

        Friend Shared Sub HandleRequest(ByVal client As NetNode.Client, ByVal message As NetNode.MessageBlock)
            Dim clsRequest As Request = Utils.Serialization.FromXmlBytes(Of Request)(message.BinaryData)

            Dim clsReply As Reply = Nothing

            Dim clsShare As Entities.SharedWatchFolder = DataStore.SharedWatchFolders.GetById(clsRequest.ShareId)
            If clsShare IsNot Nothing Then
                Select Case clsShare.ItemTypes
                    Case Entities.ItemType.Movies
                        clsReply = GetMovies.GetMovieReply(clsShare, clsRequest.DirectoryCode)
                End Select
            End If
            If clsReply Is Nothing Then clsReply = New Reply
            clsReply.InReplyToMessageId = message.Id

            Dim bData() As Byte = Utils.Serialization.ToXmlBytes(clsReply)
            client.SendMessageToTargetAsync(Manager.TargetName, ReplyCode, bData)
        End Sub


        Private Class GetMovies
            Public Shared Function GetMovieReply(ByVal share As Entities.SharedWatchFolder, ByVal directoryCode As String) As Reply
                Dim clsRet As Reply = Nothing
                If String.IsNullOrEmpty(directoryCode) Or directoryCode = "\" Then
                    clsRet = New Reply
                    Dim clsGroup As New Group("Shared Item Filters")
                    clsRet.Groups.Add(clsGroup)
                    clsGroup.Directories.Add(New Directory("\All", "Alphabetical order"))
                    clsGroup.Directories.Add(New Directory("\RecentAdditions", "Recent Additions"))

                    Dim clsGroup2 As New Group("Movie Information Filters")
                    clsRet.Groups.Add(clsGroup2)
                    clsGroup2.Directories.Add(New Directory("\Genres", "By genre"))
                    clsGroup2.Directories.Add(New Directory("\Certification", "By certification"))
                    clsGroup2.Directories.Add(New Directory("\Cast", "By actor/acress"))
                    clsGroup2.Directories.Add(New Directory("\Director", "By director"))
                    clsGroup2.Directories.Add(New Directory("\Writer", "By writer"))

                ElseIf Not directoryCode.StartsWith("\"c) Then
                    clsRet = New Reply
                    'erranous directory, must start with "\"
                Else
                    Dim aParts() As String = directoryCode.Substring(1).Split("\"c)
                    Select Case aParts(0).ToLower
                        Case "genres"
                            clsRet = GetByGenres(share, directoryCode, aParts)
                        Case "all"
                            clsRet = GetAll(share, directoryCode, aParts)
                        Case Else
                            clsRet = New Reply
                    End Select
                End If
                Return clsRet
            End Function

            Private Shared Function GetByGenres(ByVal share As Entities.SharedWatchFolder, ByVal directoryCode As String, ByVal parts() As String) As Reply
                Dim clsRet As New Reply

                If parts.Length > 1 AndAlso parts(1) = "Uncategorized" Then
                    Dim clsGroup As New Group("Uncategorized movies")
                    clsRet.Groups.Add(clsGroup)
                    clsGroup.Items = DataStore.SharedItems.GetAllMoviesWithoutGenres
                Else
                    Dim aMediaInfos As Generic.List(Of Entities.MediaInfo)
                    aMediaInfos = DataStore.MediaInfo.GetAllByShareId(share.Id)

                    Dim strSelectedKey As String = ConcatArrayToDirectory(parts, 1)

                    Dim aGenres As New Generic.Dictionary(Of String, String)
                    Dim aValidSharedItemIds As New Generic.Dictionary(Of Integer, String)
                    For Each clsItem As Entities.MediaInfo In aMediaInfos
                        If clsItem.Genres IsNot Nothing AndAlso clsItem.Genres.Count > 0 Then
                            Dim strKey As String = ConcatArrayToDirectory(clsItem.Genres) ' clsItem.Genres(0).ToLower
                            If strKey = strSelectedKey Then
                                aValidSharedItemIds.Add(clsItem.SharedItemId, Nothing)
                            ElseIf strKey.StartsWith(strSelectedKey) Then
                                aValidSharedItemIds.Add(clsItem.SharedItemId, Nothing)
                                Dim strExtra As String = strKey.Substring(strSelectedKey.Length)
                                If strExtra.StartsWith("\"c) Then strExtra = strExtra.Substring(1)
                                Dim iPos As Integer = strExtra.IndexOf("\"c, 1)
                                If iPos > 0 Then strExtra = strExtra.Substring(0, iPos)
                                If Not aGenres.ContainsKey(strExtra) Then
                                    aGenres.Add(strExtra, strExtra)
                                End If
                            End If
                        End If
                    Next

                    Dim clsGroup As New Group("Genres")
                    clsRet.Groups.Add(clsGroup)
                    If parts.Length = 1 Then clsGroup.Directories.Add(New Directory(String.Format("{0}\Uncategorized", directoryCode), "(Uncategorized)"))
                    For Each strGenre As String In aGenres.Values
                        clsGroup.Directories.Add(New Directory(String.Format("{0}\{1}", directoryCode, strGenre), strGenre))
                    Next

                    If parts.Length > 1 Then
                        Dim clsSB As New System.Text.StringBuilder
                        For i As Integer = 1 To parts.Count - 1
                            If clsSB.Length > 0 Then clsSB.Append(", ")
                            clsSB.Append(parts(i))
                        Next
                        clsGroup = New Group(String.Format("Movies in genre {0}, *", clsSB.ToString))
                        clsRet.Groups.Add(clsGroup)
                        Dim aItems As Generic.List(Of Entities.SharedItem)
                        aItems = DataStore.SharedItems.GetAllBySourceWatchFolderId(share.Id)
                        For Each clsItem As Entities.SharedItem In aItems
                            If aValidSharedItemIds.ContainsKey(clsItem.Id) Then
                                clsGroup.Items.Add(clsItem)
                            End If
                        Next
                    End If
                End If
                Return clsRet
            End Function
            Private Shared Function ConcatArrayToDirectory(ByVal array As Generic.List(Of String)) As String
                Dim clsSb As New System.Text.StringBuilder
                For Each strItem As String In array
                    If clsSb.Length > 0 Then clsSb.Append("\"c)
                    clsSb.Append(strItem)
                Next
                Return clsSb.ToString
            End Function
            Private Shared Function ConcatArrayToDirectory(ByVal array() As String, ByVal start As Integer) As String
                Dim clsSb As New System.Text.StringBuilder
                For i As Integer = start To array.Length - 1
                    If clsSb.Length > 0 Then clsSb.Append("\"c)
                    clsSb.Append(array(i))
                Next
                Return clsSb.ToString
            End Function

            Private Shared Function GetAll(ByVal share As Entities.SharedWatchFolder, ByVal directoryCode As String, ByVal parts() As String) As Reply
                Dim clsRet As New Reply

                Dim clsGroup As New Group(Nothing, True)
                clsRet.Groups.Add(clsGroup)

                clsGroup.Items = DataStore.SharedItems.GetAllBySourceWatchFolderId(share.Id)
                Return clsRet
            End Function
        End Class




        Friend Shared Sub HandleReply(ByVal client As NetNode.Client, ByVal message As NetNode.MessageBlock)
            Utils.Threading.Invoke(AddressOf HandleReply_CallBack, client, message)
        End Sub
        Private Shared Sub HandleReply_CallBack(ByVal client As NetNode.Client, ByVal message As NetNode.MessageBlock)
            Dim clsReply As Reply = Utils.Serialization.FromXmlBytes(Of Reply)(message.BinaryData)
            Manager.OnGetShareItemsReply(client, clsReply)
        End Sub
    End Class


End Namespace
